home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Graphics Samples / Getting Started w⁄GX ƒ / Getting Started GX - shapes.c < prev    next >
Encoding:
Text File  |  1996-04-15  |  31.1 KB  |  952 lines  |  [TEXT/KAHL]

  1. /**
  2.  --
  3.  --
  4.  --        App:        Getting Started w/QD GX (WWDC)
  5.  --
  6.  -- 
  7.  --        Version:    1.0     4/93:    added all of the calls required to support the "Getting 
  8.  --                                    Started with QuickDraw™ GX" session at the WWDC '93     
  9.  --
  10.  --                            8/93:    updated file to work with the ß2 "GXified" interface files
  11.  --
  12.  --                               12/93:    updated for b3. - dmh & pla
  13.  --                               3/94:    corrected usage of GXSetShapeAttributes. - dmh
  14.  --                               8/94:    universalized. - dmh
  15.  --            
  16.  --                            4/96 bob    Updated #includes to support changed GX Library names.
  17.  --                                        Changed fixed to Fixed.
  18.  --                                        Updated the note regarding the files needed to run.
  19.  --                                        Updated the copyright date.
  20.  --            
  21.  --            
  22.  --        File:        Getting Started GX - shapes.c 
  23.  --
  24.  --        Comments:    This code demonstrates creates, manipulates, and draws all of the QuickDraw
  25.  --                    GX shapes used in this app. This is the same code which was used during the
  26.  --                    "Getting Started With QuickDraw GX" WWDC '93 session.
  27.  --
  28.  --                    This application will also support multiple windows. We present two menus
  29.  --                    to the user to draw into the contents of the window. The "Graphics" menu
  30.  --                    allows the user to create a platinum rectangle and rotate a text shape ("QD GX")
  31.  --                    from the lower left corner 45 degrees. The font used within the text shape
  32.  --                    is the "Skia" font. This font contains font variation information. This information
  33.  --                    allows us to change the various axes within the font to receive different
  34.  --                    effects. In our case, we retrieve information regarding the 'wght' axis of the
  35.  --                    font and set it to the maximum width allowed. By setting the 'wght' axis to the
  36.  --                    maximum, we receive nice fat letters. Each letter of the text shape is colored
  37.  --                    in a different CMYK color. We will also outline each character in black. Finally, 
  38.  --                    we add a star pattern to the "X". 
  39.  --
  40.  --                    As each letter is drawn, you can see the "gxAndMode" transfer mode applied as 
  41.  --                    the characters overlap.
  42.  --                    
  43.  --                    The second menu "Typography", creates and manipulates a layout shape. The first 
  44.  --                    menu item will create the layout shape. Once you have created the layout shape,
  45.  --                    you will recieve the "as" ligature in "Nasty", swashes for the "C", "N", and "D",
  46.  --                    the final form of "e" in "Dude", and the automatic kerning of "WAVE".
  47.  --
  48.  --                    For all of the layout effects to work, you need the following fonts installed into 
  49.  --                    your system:
  50.  --
  51.  --                    • Hoefler (this font will be automatically installed, if you use the Installer Script)
  52.  --                    • Skia
  53.  --                    • HonMincho
  54.  --                    • Times
  55.  --
  56.  --                    All of the fonts listed above (except Hoefler), can be found in the "Testing Fonts"
  57.  --                    Folder contained within the "• Open Me First! •" folder. If these fonts are _not_
  58.  --                    installed, you will recieve font substitution, and you will receive interesting
  59.  --                    characters when the Kanji text is drawn.
  60.  --
  61.  --                    The next item allows you to add two-byte Kanji text to the layout shape. The last
  62.  --                    item allows you to perspect the layout shape.
  63.  --
  64.  --
  65.  --        Components:    Getting Started GX - main.c
  66.  --                    Getting Started GX - main.h
  67.  --                    Getting Started GX - shapes.c
  68.  --                    Getting Started GX - printing.c
  69.  --                    Getting Started GX - misc.c
  70.  --                    Getting Started QD GX.π.rsrc
  71.  --
  72.  --                    The file titled: "Getting Started GX - main.c" contains the code required
  73.  --                    to intialize and tear down the QuickDraw GX world, and the event loop.
  74.  --
  75.  --                    The file titled: "Getting Started GX - printing.c" contains the code required
  76.  --                    to print the contents of the window.
  77.  --        
  78.  --        History:    4/93    New        PLA
  79.  --                    12/93    Updated to use the new/changed line layout feature constants with QD GX ß3 PLA    
  80.  --        
  81.  --        QuickDraw GX
  82.  --        Libraries
  83.  --        Used:        This application uses the following QuickDraw GX library code files:
  84.  --                    "ColorLibrary.c", "FontLibrary.c", "GraphicsDebugLibrary.c", "LayoutLibrary.c",
  85.  --                    "ShapeLibrary.c", "TransferModeLibrary.c", and "TransformLibrary.c".
  86.  --        
  87.  --        
  88.  --        Notes:        1) Print this file in landscape for the best results
  89.  --                    2) If you are using THINK C v6.x, I have added THINK markers to navigate the code.
  90.  --                    3) This code was adapted from the "Banana Jr." QuickDraw GX sample.
  91.  --
  92.  --
  93.  --        Author:        Pete "Luke" Alexander
  94.  --                    Developer Technical Support
  95.  --                    AppleLink: DEVSUPPORT
  96.  --
  97.  --        
  98.  --        ©1992 - 1996  Apple Computer, Inc. 
  99.  --        All rights reserved.
  100.  --
  101.  **/
  102.  
  103.  
  104. #include <events.h>
  105. #include <memory.h>
  106. #include <windows.h>
  107.  
  108. #include "FontLibrary.h"
  109. #include "GraphicsLibraries.h"
  110. #include <GXEnvironment.h>
  111. #include <GXErrors.h>
  112. #include "QDLibrary.h"
  113. #include <GXPrinting.h>
  114. #include <LayoutFeatureConstants.h>
  115.  
  116. #include "Getting Started GX - main.h"
  117.  
  118. #include "LayoutLibrary.h"
  119. #include <GXLayout.h>
  120.  
  121. //
  122. //    Set up the title and size of the window
  123. //
  124. Str255         gWindowTitle = "\p Various Shapes...";
  125. Rect         gWindowQDRect  = {50, 10, 470, 590};
  126.  
  127.  
  128. //
  129. //    If gDebugging = TRUE, graphics library errors and notices will be posted.  This functionality will only work with 
  130. //    the "debugging" version of the QuickDraw GX init.  If this version of the init is not installed, nothing bad will happen, 
  131. //    but these  functions will not work.
  132. //
  133. Boolean        gDebugging = true;
  134.  
  135. //
  136. //    Set  "gGiveMeValidation" to TRUE, if you will receive run-time validation.
  137. //
  138. Boolean        gGiveMeValidation = true;
  139.  
  140.  
  141. //
  142. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the GXNewGraphicsClient routine
  143. //    in main () within the Getting Started GX - main.c file.  You can determine the amount of graphics heap
  144. //    required by using GraphicsBug.I'm giving it 500K, since we need a bunch if we have several windows open.
  145. //
  146. long        gGraphicsHeapSize = 500;
  147.  
  148. gxFont        gtheSkiaFont;
  149.  
  150.  
  151.  
  152. /*------ DoInitialization ---------------------------------------------------------------------------------*/
  153. //
  154. //    In this function we create and gxInitialize the the private document structure for a new window.  This
  155. //    structure contains the print job and the shape which is drawn in the window.  We store this data in
  156. //    a handle and hang it off the window's refCon field for easy retrieval.  By doing this, rather than using
  157. //    globals, we can create many windows containing unique print jobs and shapes. 
  158. //
  159. OSErr DoInitialization(wind)
  160. WindowPtr wind;
  161. {
  162.     OSErr        err;
  163.     gxJob        docJob;
  164.     gxShape        docPage;
  165.     TH_Doc        windDoc;
  166.  
  167.     //
  168.     //     Create the page shape. We set the unique items attribute to make sure that each item added to the
  169.     //     picture has a unique reference. 
  170.     //
  171.     docPage = GXNewShape(gxPictureType);
  172.     GXSetShapeAttributes(docPage, GXGetShapeAttributes(docPage)|gxUniqueItemsShape);
  173.     
  174.     //
  175.     //     Create a print job for this document.  This will be the same as the system default until the user
  176.     //     goes through the dialogs for Page Setup or Print…
  177.     //
  178.     err = GXNewJob(&docJob);
  179.  
  180.     //
  181.     //     If there are no errors, create a handle the size of our document structure and store the print job and page shape
  182.     //     in it.  Store the handle in the window's refCon field so that we can get at it.  (Note that the utility routines
  183.     //     "GetDocJob" and "GetDocShape" can be used to do this easily.
  184.     //
  185.     if (!err)
  186.     {
  187.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  188.  
  189.         if (!windDoc)
  190.             err = MemError();
  191.         else
  192.         {
  193.             (*windDoc)->docJob = docJob;
  194.             (*windDoc)->docPage = docPage;
  195.             ((WindowPeek) wind)->refCon = (long) windDoc;
  196.         }
  197.  
  198.     //
  199.     //    If there are no errors, install our override for gxPrintingEvent (which will
  200.     //    allow us to update our windows as the printing dialogs are moved around.
  201.     //
  202.     GXInstallApplicationOverride(docJob, gxPrintingEventMsg, NewGXPrintingEventProc(MyPrintingEventOverride));
  203.     }
  204. }
  205.  
  206.  
  207. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  208. //
  209. //    We retrieve the GX picture attached the window and draw the contents of the window.
  210. // 
  211. void DoDraw(wind)
  212. WindowPtr wind;
  213. {
  214.      GXDrawShape (GetDocShape(wind));
  215. }
  216.  
  217.  
  218.  
  219. /*------ CreateNewLayoutShape -------------------------------------------------------------------------*/
  220. //
  221. //    We create a layout shape and added it ot the GX picture attached to the front window.
  222. // 
  223.  
  224. void CreateNewLayoutShape(WindowPtr wind)
  225. {
  226.     gxShape                thePage;
  227.     char                 *sampleText = "Catch the Nasty WAVE, Dude";
  228.     gxShape             tempLayoutShape;
  229.     gxPoint             layoutPostion = {ff(10), ff(65)};
  230.     gxRunControls        runControls;
  231.     gxRunFeature        runFeatures[3];
  232.     gxStyle                styles[3];
  233.     short                totalLengthOfLayout, 
  234.                         lengthsArray[3],
  235.                         loop;
  236.  
  237.     //
  238.     //    Retreive the GX picture attached to the front window.
  239.     //
  240.     thePage = GetDocShape(wind);
  241.  
  242.     //
  243.     //    We start by intializing the layout run controls to their default values.
  244.     //
  245.     InitializeRunControls(&runControls);
  246.         
  247.  
  248.     //
  249.     //    We need to create the style which will be used for the first run of text within our
  250.     //    layout shape: "Catch the Nasty WAVE, Dude". Within a layout shape, you have the ability to have
  251.     //    multiple runs of text. Each run can use: a different font, text size, run features,
  252.     //    run controls.
  253.     //    
  254.     //    In the case of our first run of text, we want to use Hoefler Italic and a text size of 36.
  255.     //    We set the run controls to their default setting. 
  256.     //
  257.     styles[0] = NewLayoutStyle((char *)"\pHoefler Italic", ff(36), 0, &runControls, nil, 0, nil);
  258.  
  259.  
  260.     //
  261.     //    Next, we want to turn on a couple of run features within this run of text. We start by
  262.     //    enabling the "as" ligature in "Nasty". We tell gxLine layout that we want to set the 
  263.     //    featureType of our run control to enable the ligature capabilities of Hoefler Italic, and
  264.     //    we then enable the "as" ligature. 
  265.     //
  266.     runFeatures[0].featureType = ligatureType;
  267.     runFeatures[0].featureSelector = ligatureRareOnSelector;
  268.  
  269.  
  270.     //
  271.     //    !! •• ß3 Change •• !!
  272.     //
  273.     //    The next thing we need to tell line layout to do is enable the swash capabilities of our 
  274.     //    "C" and "N" characters contained within the first run of text. These swashes are part of the 
  275.     //    Hoefler Italic font. We acheive this goal by setting the runFeatures featureType
  276.     //    to characterAlternativesType with a featureSelector of 1.
  277.     //
  278.     //    This is an example were the characterAlternativesType feature is font dependent. Each TrueType
  279.     //    GX font can contain 0 or more additional character alternatives selectors defined by a font.
  280.     //    In the case of the Hoefler Italic font, the 1st feature enables the "C" and "N" swashes of 
  281.     //    each word.
  282.     //
  283.     runFeatures[1].featureType = characterAlternativesType;
  284.     runFeatures[1].featureSelector = 1;
  285.     
  286.     //
  287.     //    After we have created the run features we need, we set the run features of our
  288.     //    style to use them.
  289.     //
  290.     GXSetStyleRunFeatures(styles[0], 2, runFeatures);
  291.     
  292.     //     
  293.     //    In the second style we need to create is for the "WAVE!" run. For this run of text, 
  294.     //    we want the font to be Times Roman, 38 point text size, and use the default run 
  295.     //    controls. This style will also give us automatic kerning of the run.
  296.     //
  297.     styles[1] = NewLayoutStyle((char *)"\pTimes Roman", ff(38), 0, &runControls, nil, 0, nil);
  298.     
  299.  
  300.     //
  301.     //    The final style we need to create is used by the last run of text "dude". 
  302.     //
  303.     styles[2] = NewLayoutStyle((char *)"\pHoefler Italic", ff(34), 0, &runControls, nil, 0, nil);
  304.  
  305.     //
  306.     //    The run features used for the style reference by the last run of text will
  307.     //    enable the final form of "e" in "dude". We enable these smartSwashType feature and
  308.     //    turn on the final form of "e".
  309.     //
  310.     runFeatures[2].featureType = smartSwashType;
  311.     runFeatures[2].featureSelector = lineFinalSwashesOnSelector;
  312.     
  313.     //
  314.     //    Update the style used for this run of text to use the our run features which
  315.     //    enable the final form "e".
  316.     //
  317.     GXSetStyleRunFeatures(styles[2], 3, runFeatures);
  318.     
  319.     //
  320.     //    The "lengthsArray" defines the length of each run of text used within our layout shape. 
  321.     //    In our case, the first run of text is 16 characters, the second run is 4 characters,
  322.     //    and the final run is 5 characters.
  323.     //
  324.     lengthsArray[0] = 15;    lengthsArray[1] = 6;  lengthsArray[2] = 5;
  325.  
  326.     totalLengthOfLayout = 26;
  327.  
  328.     //
  329.     //    We now update our layout shape to include our 2 new styles. When our layout shape
  330.     //    is drawn, the "C" and "N" swashes, "as" ligature, and the kerning of "WAVE!" will
  331.     //    appear.
  332.     //
  333.     tempLayoutShape = GXNewLayout(1, &totalLengthOfLayout, (void *) &sampleText, 
  334.                                   3, lengthsArray, styles, 0, nil, nil, nil, &layoutPostion);
  335.  
  336.     GXSetPictureParts(thePage, 0, 0, 1, &tempLayoutShape, nil, nil, nil);
  337.     GXDisposeShape(tempLayoutShape);
  338.     
  339.  
  340.       //
  341.       //    We can now dispose of our styles because they have been added into our layout shape.
  342.       //    They are no longer needed....
  343.      //
  344.     for (loop = 0; loop < 3; loop++) 
  345.       GXDisposeStyle(styles[loop]);
  346.  
  347.  
  348.      //
  349.     // Invalidate the window's portRect so that everything gets updated.
  350.      //
  351.     SetPort(wind);
  352.     InvalRect(&wind->portRect);
  353. }
  354.  
  355.  
  356.  
  357.  
  358. /*------ AddKanjiToLayout -----------------------------------------------------------------------------*/
  359. //
  360. //    This removes single byte roman version of "WAVE", and replaces it with the two-byte Kanji version.
  361. //
  362. void AddKanjiToLayout(WindowPtr wind)
  363. {
  364.     gxShape        thePage;
  365.     gxShape        tempLayoutShape;
  366.     gxShape        layoutShapeFromPicture;
  367.     gxStyle        kanjiStyle;
  368.     char         *kanjiSampleText = "îgòQ";
  369.     short        lengthsArray[1];
  370.  
  371.     //
  372.     //    Retreive the GX picture attached to the front window.
  373.     //
  374.     thePage = GetDocShape(wind);
  375.  
  376.     //
  377.     //    Retrieve the layout shape from the picture and make a copy of it.
  378.     //
  379.     GXGetPictureParts(thePage, 1, 1, &layoutShapeFromPicture, nil, nil, nil);
  380.     tempLayoutShape = GXCopyToShape (nil, layoutShapeFromPicture);
  381.     
  382.     //
  383.     //    Create a new style which uses the "HonMincho Medium" font and set the encoding. If
  384.     //    you do not set the encoding for this style, QD GX will not know how to create
  385.     //    the characters passed, thereby using the characters in a different manner than
  386.     //    you intended.
  387.     //
  388.     kanjiStyle = NewLayoutStyle((char *)"\pHonMincho Medium", ff(39), 0, nil, nil, 0, nil);
  389.     GXSetStyleEncoding (kanjiStyle, gxMacintoshPlatform, gxJapaneseScript, gxJapaneseLanguage);
  390.  
  391.     //
  392.     //    We now insert (i.e. replace the roman characters) the new Kanji characters on top 
  393.     //    of the roman "WAVE". We know the roman characters start at byte location 16 and
  394.     //    end at 21.
  395.     //
  396.     lengthsArray[0] = 4;
  397.     
  398.     GXSetLayoutParts(tempLayoutShape, 16, 21, 1, lengthsArray,(void *) &kanjiSampleText, 
  399.                      1, lengthsArray, &kanjiStyle, 0, nil, nil);
  400.  
  401.     GXDisposeStyle(kanjiStyle);
  402.     
  403.     //
  404.     //    We move our newly modified layout shape and add it to our picture.
  405.     //
  406.     GXMoveShape (tempLayoutShape, 0, ff(75));
  407.     GXValidateShape (tempLayoutShape);
  408.     
  409.     GXSetPictureParts(thePage, 2, 0, 1, &tempLayoutShape, nil, nil, nil);
  410.     GXDisposeShape(tempLayoutShape);
  411.  
  412.  
  413.     //
  414.     // Invalidate the window's portRect so that everything gets updated.
  415.     //
  416.     SetPort(wind);
  417.     InvalRect(&wind->portRect);
  418. }
  419.  
  420.  
  421. /*------ PerspectLayout -------------------------------------------------------------------------------*/
  422. //
  423. //    Since a layout shape is treated like any other graphics shape, we can perspect it and preserve
  424. //    all of the layout features when enabled when we created the shape, therefore this function will
  425. //    perspect the current layout shape.
  426. //
  427. void PerspectLayout(WindowPtr wind)
  428. {
  429.     gxShape        thePage;
  430.     gxShape        tempLayoutShape;
  431.     gxShape        layoutShapeFromPicture;
  432.     gxRectangle layoutBounds;
  433.     gxMapping    layoutMapping;
  434.     Fixed         x, y;
  435.  
  436.     //
  437.     //    Retreive the GX picture attached to the front window.
  438.     //
  439.     thePage = GetDocShape(wind);
  440.  
  441.     //
  442.     //    Retrieve the layout shape from the picture and make a copy of it.
  443.     //
  444.     GXGetPictureParts(thePage, 2, 1, &layoutShapeFromPicture, nil, nil, nil);
  445.     tempLayoutShape = GXCopyToShape (nil, layoutShapeFromPicture);
  446.  
  447.     //
  448.     // Determine the center of our layout shape.
  449.     //
  450.     GXGetShapeBounds(tempLayoutShape, 0L, &layoutBounds);
  451.     x = layoutBounds.left + layoutBounds.right >> 1;
  452.     y = layoutBounds.top + layoutBounds.bottom >> 1;
  453.         
  454.     //
  455.     //    We scale the layout to enable us to get a better visual effect when we prespect it, 
  456.     //    and we move it to prevent it fonr drawing on top of the latest layout shape added 
  457.     //    to the picture.
  458.     //    
  459.     GXScaleShape(tempLayoutShape, ff(2), ff(2), 0, 0);
  460.     GXMoveShape(tempLayoutShape, 0, ff(100));
  461.  
  462.     //
  463.     //    Retrieve the gxMapping of our layout shape and perspect it, pulling along and
  464.     //    down the x-axis.
  465.     //
  466.     GXGetShapeMapping(tempLayoutShape, &layoutMapping);
  467.     layoutMapping.map[0][2] = ff(30);
  468.     layoutMapping.map[1][2] = ff(1);
  469.     GXSetShapeMapping(tempLayoutShape, &layoutMapping);
  470.  
  471.     //
  472.     //    Add our newly perspected layout shape to our picture.
  473.     //
  474.     GXSetPictureParts(thePage, 3, 0, 1, &tempLayoutShape, nil, nil, nil);
  475.     GXDisposeShape(tempLayoutShape);
  476.     
  477.             
  478.     //
  479.     //     Invalidate the window's portRect so that everything gets updated.
  480.     //
  481.     SetPort(wind);
  482.     InvalRect(&wind->portRect);
  483. }
  484.  
  485.  
  486. /*------ CreateABlackRectangle ------------------------------------------------------------------------*/
  487. //
  488. //    We want to create a black rectangle. Within GX, you need to define the geometry and create a shape.
  489. //    You are then ready to draw the particular shape.
  490. //
  491. void CreateABlackRectangle (WindowPtr wind)
  492. {
  493.     gxShape            thePage;
  494.     gxShape            tempRectShape;
  495.     gxRectangle     rectGeometry = {ff(70), ff(70), ff(280), ff(275)};    
  496.  
  497.     //
  498.     //    Retreive the GX picture attached to the front window.
  499.     //
  500.     thePage = GetDocShape(wind);
  501.  
  502.     //
  503.     //    Create the rectangle which is defined by the rectangular geometry contained within 
  504.     //    "rectGeometry" and add it to our picture.
  505.     //
  506.      tempRectShape = GXNewRectangle(&rectGeometry); 
  507.      GXSetPictureParts(thePage, 0, 0, 1, &tempRectShape, nil, nil, nil);
  508.     GXDisposeShape(tempRectShape);  
  509.  
  510.     //
  511.     //     Invalidate the window's portRect so that everything gets updated.
  512.     //
  513.     SetPort(wind);
  514.     InvalRect(&wind->portRect);
  515. }
  516.  
  517.  
  518. /*------ ColorTheRectangle ----------------------------------------------------------------------------*/
  519. //
  520. //     We want to color our rectangle a more interesting color to allow the transfer modes we will add to 
  521. //    the text shape to appear, therefore we color our rectangle "platinum". We use the common color
  522. //    library to perform the coloring. In this case, the library creates the platinum color in RGB space.
  523. //
  524. void ColorTheRectangle (WindowPtr wind)
  525. {
  526.     gxShape        thePage;
  527.     gxShape        tempRectShape;
  528.  
  529.     //
  530.     //    Retreive the GX picture attached to the front window.
  531.     //
  532.     thePage = GetDocShape(wind);
  533.     
  534.     //
  535.     //    Get a reference to our black rectangle and change the color to platinum.
  536.     //
  537.     GXGetPictureParts(thePage, 1, 1, &tempRectShape, nil, nil, nil);
  538.     SetShapeCommonColor (tempRectShape, platinum );
  539.  
  540.  
  541.     //
  542.     //     Invalidate the window's portRect so that everything gets updated.
  543.     //
  544.     SetPort(wind);
  545.     InvalRect(&wind->portRect);
  546. }
  547.  
  548.  
  549.  
  550. /*------ CreateAQ -------------------------------------------------------------------------------------*/
  551. //
  552. //    We want to create the first text shape - "Q". So, we need to create the following GX objects:
  553. //    the text shape containing the "Q", the CMYK color used to color "Q", a style which defines the 
  554. //    font, font size, the 'wght', pen width, and pen drawing location.
  555. //
  556. void CreateAQ (WindowPtr wind)
  557. {
  558.     gxShape                thePage;
  559.     gxShape                tempTextShape;
  560.     Fixed                maxVariationValue;
  561.     gxFontVariation        fontVariation;
  562.     long                result;
  563.     
  564.     //
  565.     //    Retreive the GX picture attached to the front window.
  566.     //
  567.     thePage = GetDocShape(wind);
  568.  
  569.     //
  570.     //    Create a new style to contain: the font, font size, the 'wght' axis of the font set to the
  571.     //    maximum value allowed for this font, set the pen size, and the location of the pen when 
  572.     //    drawing.
  573.     //
  574.     gOurStyle = GXNewStyle ();
  575.     
  576.     GXSetStylePen(gOurStyle, ff(2));
  577.     GXSetStyleAttributes(gOurStyle, gxOutsideFrameStyle);
  578.     
  579.     GXSetStyleTextSize(gOurStyle, ff(135));
  580.     gtheSkiaFont = FindPNameFont (gxFullFontName, "\pSkia Regular");
  581.     GXSetStyleFont(gOurStyle, gtheSkiaFont);
  582.     
  583.     result = GXFindFontVariation(gtheSkiaFont, 'wght', nil, nil, &maxVariationValue, nil);
  584.  
  585.     //
  586.     //    If the "result" is good, we proceed to set the "wght" axis to the maximum value. If the 
  587.     //    "result" is bad, this probably means that the "Skia" font has not been installed. In this
  588.     //    case we cannot set the "wght" axis, so we do not and we alert the user. We will be able 
  589.     //    to continue at this gxPoint, but we will not have the fat juicy letters.
  590.     //
  591.     if (result) {
  592.         fontVariation.name     = 'wght';
  593.         fontVariation.value    = maxVariationValue;
  594.     
  595.          GXSetStyleFontVariations(gOurStyle, 1, &fontVariation);
  596.          
  597.     } else  DebugStr ("\p NO 'wght' axis....");
  598.  
  599.     //
  600.     //    Set up as CMYK color space which will used to color all of our text shapes. The "Q" will
  601.     //    be colored in magenta. Each text shape will use a different CMYK color. We change the setting
  602.     //    for our "gTextColor" when we create each new shape.
  603.     //
  604.     gTextColor.space                     = gxCMYKSpace;
  605.     gTextColor.element.cmyk.cyan         = 0x0000;
  606.     gTextColor.element.cmyk.magenta     = 0xffff;
  607.     gTextColor.element.cmyk.yellow         = 0x0000;
  608.     gTextColor.element.cmyk.black         = 0x0000;
  609.     gTextColor.profile                     = nil;
  610.     
  611.     //
  612.     //    Create the "Q", and set it's: style, transfer mode, color, and shape fill.
  613.     //
  614.     tempTextShape = GXNewText (1, (unsigned char*) "Q", &gTextLocation);
  615.      SetShapeCommonTransfer(tempTextShape, gxAndMode);
  616.     GXSetShapeStyle(tempTextShape, gOurStyle);
  617.      GXSetShapeColor(tempTextShape, &gTextColor);
  618.  
  619.     gRotatedTransform = GXNewTransform ();
  620.     GXRotateTransform(gRotatedTransform, -ff(40), ff(200), ff(200));
  621.     GXMoveTransform(gRotatedTransform, ff(40), ff(100));
  622.  
  623.      GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  624.     GXDisposeShape(tempTextShape);  
  625.  
  626.     //
  627.     //     Invalidate the window's portRect so that everything gets updated.
  628.     //
  629.     SetPort(wind);
  630.     InvalRect(&wind->portRect);
  631. }
  632.                     
  633.                         
  634. /*------ OutlineTheQ ----------------------------------------------------------------------------------*/
  635. //
  636. //    We want to outline our "Q" in black. So, we retrieve a copy of the "Q" from our picture, make
  637. //    a copy, change the shape fill to outline, color the outline back, and add the copy to our picture.
  638. //
  639. void OutlineTheQ (WindowPtr wind)
  640. {
  641.     gxShape        thePage;
  642.     gxShape        tempTextShape;
  643.     gxShape        theQFromThePicture;
  644.  
  645.     //
  646.     //    Retreive the GX picture attached to the front window.
  647.     //
  648.     thePage = GetDocShape(wind);
  649.  
  650.     //
  651.     //    Retrieve the "Q" from our picture and make a copy.
  652.     //
  653.     GXGetPictureParts(thePage, 2, 1, &theQFromThePicture, nil, nil, nil);
  654.     tempTextShape = GXCopyToShape (nil, theQFromThePicture);
  655.  
  656.     //
  657.     //    Set the shape fill to be outline of our "Q", center the pen on the geometry,
  658.     //  and color it black.
  659.     //
  660.     GXSetShapeType(tempTextShape, gxPathType); 
  661.     GXSetShapeFill(tempTextShape, gxClosedFrameFill);
  662.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  663.     SetShapeCommonColor(tempTextShape, gxBlack);
  664.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  665.  
  666.     //
  667.     //    Add the new outlined "Q" to our picture.
  668.     //
  669.     GXSetPictureParts(thePage, 3, 0, 1, &tempTextShape, nil, nil, nil);
  670.     GXDisposeShape(tempTextShape);  
  671.  
  672.     //
  673.     //     Invalidate the window's portRect so that everything gets updated.
  674.     //
  675.     SetPort(wind);
  676.     InvalRect(&wind->portRect);
  677. }
  678.  
  679.  
  680. /*------ CreateAD -------------------------------------------------------------------------------------*/
  681. //
  682. //    We want to add a "D" to our picture, which is colored a yellow CMYK color, and outline it.
  683. //
  684. void CreateAD (WindowPtr wind)
  685. {
  686.     gxShape                thePage;
  687.     gxShape                tempTextShape;
  688.  
  689.     //
  690.     //    Retreive the GX picture attached to the front window.
  691.     //
  692.     thePage = GetDocShape(wind);
  693.     
  694.     //
  695.     //    Set the CYMK color to be yellow.
  696.     //
  697.     gTextColor.element.cmyk.magenta = 0x0000;
  698.     gTextColor.element.cmyk.yellow = 0xffff;
  699.     
  700.     //
  701.     //    Create the "D", set it's transfer mode to gxAndMode with the transfer mode library, 
  702.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  703.     //
  704.     gTextLocation.x += ff(75);
  705.      tempTextShape = GXNewText (1, (unsigned char*) "D", &gTextLocation);
  706.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  707.       GXSetShapeStyle(tempTextShape, gOurStyle);
  708.      GXSetShapeColor(tempTextShape, &gTextColor);
  709.  
  710.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  711.  
  712.     //
  713.     //    Create the outline of the "D", center the pen on the geometry of the outline,
  714.     //    color it black and add it to the picture.
  715.     //
  716.     GXSetShapeType(tempTextShape, gxPathType); 
  717.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  718.     GXSetShapeFill(tempTextShape,  gxClosedFrameFill);
  719.     SetShapeCommonColor(tempTextShape, gxBlack);
  720.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  721.  
  722.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  723.     GXDisposeShape(tempTextShape);  
  724.  
  725.     //
  726.     //     Invalidate the window's portRect so that everything gets updated.
  727.     //
  728.     SetPort(wind);
  729.     InvalRect(&wind->portRect);
  730. }
  731.  
  732.  
  733.  
  734. /*------ CreateAG -------------------------------------------------------------------------------------*/
  735. //
  736. //    We want to add a "G" to our picture, which is colored a yellow CMYK color, and outline it.
  737. //
  738. void CreateAG (WindowPtr wind)
  739. {
  740.     gxShape                thePage;
  741.     gxShape                tempTextShape;
  742.  
  743.     //
  744.     //    Retreive the GX picture attached to the front window.
  745.     //
  746.     thePage = GetDocShape(wind);
  747.     
  748.     //
  749.     //    Set the CYMK color to be yellow.
  750.     //
  751.     gTextColor.element.cmyk.cyan = 0xffff;
  752.     gTextColor.element.cmyk.yellow = 0x0000;
  753.  
  754.     //
  755.     //    Create the "G", set it's transfer mode to gxAndMode with the transfer mode library, 
  756.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  757.     //
  758.     gTextLocation.x += ff(75);
  759.      tempTextShape = GXNewText (1, (unsigned char*) "G", &gTextLocation);
  760.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  761.      GXSetShapeStyle(tempTextShape, gOurStyle);
  762.      GXSetShapeColor(tempTextShape, &gTextColor);
  763.  
  764.     GXSetShapeType(tempTextShape, gxPathType); 
  765.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  766.  
  767.     //
  768.     //    Create the outline of the "G" and add it to the picture.
  769.     //
  770.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  771.     GXSetShapeFill (tempTextShape,  gxClosedFrameFill);
  772.     SetShapeCommonColor (tempTextShape, gxBlack );
  773.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  774.     
  775.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  776.     GXDisposeShape(tempTextShape);  
  777.  
  778.  
  779.     //
  780.     // Invalidate the window's portRect so that everything gets updated.
  781.     //
  782.     SetPort(wind);
  783.     InvalRect(&wind->portRect);
  784. }
  785.  
  786.  
  787.  
  788. /*------ CreateAX -------------------------------------------------------------------------------------*/
  789. //
  790. // We create our "X", outline it, and fill it with stars.
  791. //
  792. void CreateAX (WindowPtr wind)
  793. {
  794.     gxShape                thePage;
  795.     gxShape                tempTextShape;
  796.     gxShape             starShape;
  797.     gxRectangle         starShapeBounds;
  798.     gxPatternRecord        starPattern;
  799.     
  800.     long starGeometry[] = {    1, //  number of contours
  801.                             5, //  number of points 
  802.                               ff(60), 0, ff(90), ff(90),  ff(0), ff(30),  ff(120), ff(30), ff(0), ff(90)};   //  the points
  803.  
  804.     //
  805.     //    Retrieve the GX picture attached to the front window.
  806.     //
  807.     thePage = GetDocShape(wind);
  808.  
  809.      //
  810.     // Create a star shape which will be used as the fill pattern
  811.     //
  812.     starShape = GXNewPolygons((gxPolygons *) starGeometry);
  813.     GXSetShapeFill (starShape,  gxWindingFill);
  814.     GXScaleShape(starShape, fl(0.15), fl(0.15), 0, 0);
  815.  
  816.     //
  817.     //    Get the bounds of our star shape.  We use the bounds to setup the u and v vectors of the pattern 
  818.     //    record. We want "tempTextShape" to be filled  with the star where each star is placed at edge of the
  819.     //    previous star (i.e so the pattern's do not overlap).
  820.     //
  821.     //    We set up the pattern record to use our star shape and no attributes will be used when the filled
  822.     //    shape is drawn.
  823.     //    
  824.     GXGetShapeBounds(starShape, 0L, &starShapeBounds);
  825.  
  826.     starPattern.u.x = 0;
  827.     starPattern.u.y = starShapeBounds.bottom;
  828.     starPattern.v.x = starShapeBounds.right + fixed1;
  829.     starPattern.v.y = 0;
  830.  
  831.     starPattern.attributes = gxNoAttributes;
  832.     starPattern.pattern = starShape;
  833.  
  834.     //
  835.     //    Set the CYMK color to be magenta.
  836.     //
  837.     gTextColor.element.cmyk.cyan = 0x0000;
  838.     gTextColor.element.cmyk.magenta =  0xffff;
  839.  
  840.     gTextLocation.x += ff(65);
  841.     
  842.     //
  843.     //    Create our "X", set the transfer mode to AndMode using the transfer mode library, set the 
  844.     //    style, shape fill, shape type, and add the rotated transform.
  845.     //
  846.     //    We need to set our shape type to be path, which will allow us to fill it with stars. You can
  847.     //    only fill a shape which is a geometric shape type (i.e. you cannot fill a text shape). Also,
  848.     //    when you are filling a shape, it fills to the boundary of the geometry for the shape fill
  849.     //    specified.
  850.     //
  851.     //    The first "X" we add to the picture will be the outline of the "X", without the star shapew
  852.     //    fill.
  853.      tempTextShape = GXNewText (1, (unsigned char*) "X", &gTextLocation);
  854.      
  855.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  856.      GXSetShapeStyle(tempTextShape, gOurStyle);
  857.     GXSetShapeType (tempTextShape, gxPathType);
  858.     GXSetShapeFill (tempTextShape, gxClosedFrameFill);
  859.     GXSetShapeTransform(tempTextShape, gRotatedTransform);
  860.  
  861.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  862.  
  863.     //
  864.     //    Set the color for the "X", set the fill to be solid, and attach the pattern record to 
  865.     //    our shape. By attaching the pattern record to our shape, adds a unique style to our
  866.     //     shape which contains the pattern record.
  867.     //
  868.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  869.     GXSetShapeColor(tempTextShape, &gTextColor);
  870.     GXSetShapeFill (tempTextShape,  gxSolidFill);
  871.     GXSetShapePattern(tempTextShape, &starPattern);
  872.     GXDisposeShape(starShape);  
  873.  
  874.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  875.     GXDisposeShape(tempTextShape);  
  876.  
  877.     //
  878.     //     Invalidate the window's portRect so that everything gets updated.
  879.     //
  880.     SetPort(wind);
  881.     InvalRect(&wind->portRect);
  882. }
  883.  
  884.  
  885.  
  886. /*------ DoCreateNew ---------------------------------------------------------------------------------*/
  887. //
  888. //    This routine is called when a window needs to be created. We create a window and add a QuickDraw GX
  889. //    gxViewPort to allow all of the QuickDraw GX drawing to occur in the correct window.
  890. //
  891. OSErr DoCreateNew(void)
  892. {
  893.     OSErr        err;
  894.     WindowPtr    wind;
  895.     
  896.     //
  897.     //     Create a window, attach a default gxViewPort to it, create and gxInitialize our privat data
  898.     //     for it, and add a sample image to its page shape.
  899.     //
  900.  
  901.     wind = NewWindow(nil, &gWindowQDRect, gWindowTitle, true, noGrowDocProc, (WindowPtr)-1L, true, 0L);
  902.     
  903.     if (!wind)
  904.         err = MemError();
  905.     else
  906.     {
  907.         GXIgnoreGraphicsNotice(transform_already_set);
  908.         SetDefaultViewPort(GXNewWindowViewPort(wind));
  909.         GXPopGraphicsNotice();
  910.         err = DoInitialization(wind);
  911.     }
  912.  
  913.     return err;
  914. }
  915.  
  916.  
  917. /*------ DoDispose -------------------------------------------------------------------------------------*/
  918. //
  919. //    This routine is called when a window needs to be disposed of.
  920. //
  921. void DoDispose(wind)
  922. WindowPtr wind;
  923. {
  924.     TH_Doc    doc;
  925.     
  926.     /**  
  927.         You should always dispose of your GX graphics objects before tossing your window. Why? It's generally good 
  928.         form and this approach guarantees that everything is disposed. If you had not disposed of everything, the
  929.         call to DisposeWindow should dispose of the objects. If you are running the debugging version of the 
  930.         SecretGraphics init with notices set, you will receive a notice that you had not disposed of everything. You
  931.         can turn notices on in this file by setting gDebugging = TRUE (above).
  932.     **/
  933.  
  934.     doc = (TH_Doc)  GetWRefCon(wind);        // Remember, this is where we stored our private data.
  935.     
  936.     GXDisposeShape(GetDocShape(wind));         // Dispose of this doc's shape.
  937.     GXDisposeJob(GetDocJob(wind));            // Dispose of this doc's print job.
  938.     DisposHandle((Handle) doc);                // Dispose of our private data.
  939.  
  940.        DisposeWindow(wind);                    // Dispose of the window.
  941. }
  942.  
  943.  
  944. /*------ DoIdle ----------------------------------------------------------------------------------------*/
  945. //
  946. //    This routine is called to do things while we're idling through tthe event loop.
  947. //
  948. void DoIdle(WindowPtr wind)
  949. {
  950. }
  951.  
  952.